﻿// MS对COM操作复合二进制文档的类型定义
// 不要直接使用下面的定义

namespace compound_doc
{
    namespace com_type
    {
        using System;
        using System.Runtime.InteropServices;
        using ComTypes = System.Runtime.InteropServices.ComTypes;

        [Flags]
        public enum STGM : uint
        {
            /// <summary>
            /// 只读模式
            /// </summary>
            READ = 0x00000000,
            /// <summary>
            /// 只写模式
            /// </summary>
            WRITE = 0x00000001,
            /// <summary>
            /// 读写模式
            /// </summary>
            READWRITE = 0x00000002,

            /// <summary>
            /// 共享存取操作
            /// </summary>
            SHARE_DENY_NONE = 0x00000040,
            /// <summary>
            /// 拒绝共享的读操作
            /// </summary>
            SHARE_DENY_READ = 0x00000030,
            /// <summary>
            /// 拒绝共享的写操作
            /// </summary>
            SHARE_DENY_WRITE = 0x00000020,
            /// <summary>
            /// 独占的存取模式
            /// </summary>
            SHARE_EXCLUSIVE = 0x00000010,
            PRIORITY = 0x00040000,

            /// <summary>
            /// 如果已经存在一个流/存储，它将被删除；如果没有已存在的流/存储，就创建一个新的
            /// </summary>
            CREATE = 0x00001000,
            /// <summary>
            /// 保留原来的数据，并将数据保存在CONTENTS流对象中，且该流位于当前存储对象下
            /// </summary>
            CONVERT = 0x00002000,
            /// <summary>
            /// 如果已经存在了一个留或存储，调用失败
            /// </summary>
            FAILIFTHERE = 0x00000000,

            /// <summary>
            /// 所有对复合文档的修改立即生效
            /// </summary>
            DIRECT = 0x00000000,
            /// <summary>
            /// 直到提交被调用修改才被写入到复合文档，类似于数据库操作中的提交和回滚
            /// </summary>
            TRANSACTED = 0x00010000,

            NOSCRATCH = 0x00100000,
            NOSNAPSHOT = 0x00200000,

            SIMPLE = 0x08000000,
            DIRECT_SWMR = 0x00400000,

            /// <summary>
            /// 当带有这个标识的复合文档中的流或存储的父存储被释放时，它会被自动释放
            /// </summary>
            DELETEONRELEASE = 0x04000000,
        }

        public enum STATFLAG : uint
        {
            DEFAULT = 0,
            NONAME = 1,
            NOOPEN = 2
        }
        public enum STGTY : int
        {
            STORAGE = 1,
            STREAM = 2,
            LOCKBYTES = 3,
            PROPERTY = 4
        }

        public static class HRESULT
        {
            public const int S_OK = 0;
            public const int S_FALSE = 1;
        }

        internal sealed class StorageFunc
        {
            [DllImport("ole32.dll", PreserveSig = false)]
            [return: MarshalAs(UnmanagedType.Interface)]
            internal static extern IStorage StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, uint grfMode, uint reserved);

            [DllImport("ole32.dll", PreserveSig = false)]
            [return: MarshalAs(UnmanagedType.Interface)]
            internal static extern IStorage StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, IntPtr pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved);

            // HRESULT StgIsStorageFile(const WCHAR * pwcsName ); 原型函数
            // 因为无输出参数，因此PreserveSig设为true
            [DllImport("ole32.dll", PreserveSig = true)]
            internal static extern int StgIsStorageFile([MarshalAs(UnmanagedType.LPWStr)] string pwcsName);
        }

        /// <summary>
        /// IEnumSTATSTG 接口
        /// </summary>
        [ComImport, Guid("0000000d-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IEnumSTATSTG
        {
            //[PreserveSig]
            //int Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] ComTypes.STATSTG[] rgelt, out uint pceltFetched);
            [PreserveSig]
            int Next(uint celt, [MarshalAs(UnmanagedType.LPArray), Out] ComTypes.STATSTG[] rgelt, out uint pceltFetched);

            void Skip(uint celt);

            void Reset();

            [return: MarshalAs(UnmanagedType.Interface)]
            IEnumSTATSTG Clone();
        }

        /// <summary>
        /// IStorage 接口
        /// </summary>
        [ComImport, Guid("0000000b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        internal interface IStorage
        {
            void CreateStream(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStream ppstm);

            void OpenStream(string pwcsName, IntPtr reserved1, uint grfMode, uint reserved2, out IStream ppstm);

            void CreateStorage(string pwcsName, uint grfMode, uint reserved1, uint reserved2, out IStorage ppstg);

            void OpenStorage(string pwcsName, IStorage pstgPriority, uint grfMode, IntPtr snbExclude, uint reserved, out IStorage ppstg);

            void CopyTo(uint ciidExclude, IntPtr rgiidExclude, IntPtr snbExclude, IStorage pstgDest);

            void MoveElementTo(string pwcsName, IStorage pstgDest, string pwcsNewName, uint grfFlags);

            void Commit(uint grfCommitFlags);

            void Revert();

            void EnumElements(uint reserved1, IntPtr reserved2, uint reserved3, out IEnumSTATSTG ppenum);

            void DestroyElement(string pwcsName);

            void RenameElement(string pwcsOldName, string pwcsNewName);

            void SetElementTimes(string pwcsName, ComTypes.FILETIME pctime, ComTypes.FILETIME patime, ComTypes.FILETIME pmtime);

            void SetClass(Guid clsid);

            void SetStateBits(uint grfStateBits, uint grfMask);

            void Stat(out ComTypes.STATSTG pstatstg, uint grfStatFlag);
        }

        /// <summary>
        /// IStream 接口 
        /// </summary>
        /// <remarks>
        /// 实际上Microsoft.CLRAdmin空间里定义了同样的接口
        /// </remarks>
        [ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        internal interface IStream
        {
            void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);

            void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);

            void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);

            void SetSize(long libNewSize);

            void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);

            void Commit(int grfCommitFlags);

            void Revert();

            void LockRegion(long libOffset, long cb, int dwLockType);

            void UnlockRegion(long libOffset, long cb, int dwLockType);

            void Stat(out ComTypes.STATSTG pstatstg, int grfStatFlag);

            void Clone(out IStream ppstm);
        }
    }
}